<?php

namespace app\amqp\customer;

use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Wire\AMQPTable;

class DelayCustomer
{
    public function customer()
    {
        $amqpConfig = config('amqp');

        $conn = new AMQPStreamConnection(
            host: $amqpConfig['host'],
            port: $amqpConfig['port'],
            user: $amqpConfig['user'],
            password: $amqpConfig['password'],
            vhost: $amqpConfig['vhost']
        );
        $channel = $conn->channel();

        $channel->basic_qos(0, 1, false);

        // 创建正常的交换机和队列
        $channel->exchange_declare(
            exchange: $amqpConfig['exchange'],
            type: $amqpConfig['exchange_type'],
            passive: false,
            durable: true,
            auto_delete: false,
        );
        // 创建死信交换机和队列
        $deadLetterExchange = 'sms_delay_exchange';
        $deadLetterQueue = 'sms_delay_queue';
        $deadLetterRoutingKey = 'sms_delay_queue';
        $channel->exchange_declare(
            exchange: $deadLetterExchange,
            type: $amqpConfig['exchange_type'],
            passive: false,
            durable: true,
            auto_delete: false,
        );

        // 设置死信队列相关参数
        $args = new AMQPTable();
        // 设置延迟过期时间为10秒 (*1000)
        $args->set('x-message-ttl', 10000);
        // 设置死信交换器
        $args->set('x-dead-letter-exchange', $deadLetterExchange);
        // 设置死信路由键
        $args->set('x-dead-letter-routing-key', $deadLetterRoutingKey);
        // 声明死信队列
        $channel->queue_declare(
            queue: $deadLetterQueue,
            passive: false,
            durable: true,
            exclusive: false,
            auto_delete: false
        );
        // 声明队列，作为普通队列，同时将死信队列相关参数传入
        $channel->queue_declare(
            queue: 'delay_queue',
            passive: false,
            durable: true,
            exclusive: false,
            auto_delete: false,
            arguments: $args
        );

        // 将死信队列与死信交换机绑定，同时指定死信路由键
        $channel->queue_bind(
            queue: $deadLetterQueue,
            exchange: $deadLetterExchange,
            routing_key: $deadLetterRoutingKey
        );
        // 将普通队列与普通交换机绑定
        $channel->queue_bind(
            queue: 'delay_queue',
            exchange: $amqpConfig['exchange'],
            routing_key: 'delay_queue'
        );

        $channel->basic_consume(
            queue: 'sms_delay_queue',
            no_ack: false,
            callback: [$this, 'onMessage']
        );

        register_shutdown_function([$this, 'shutdown'], $channel, $conn);

        // 阻塞队列监听事件
        $channel->consume();
    }

    public function onMessage(AMQPMessage $message) {
        var_dump($message->body, date('Y-m-d H:i:s'));
        // 手动发送ACK
        $message->ack();
    }

    public function shutdown($channel, $connection)
    {
        $channel->close();
        $connection->close();
    }
}
